Many large complex systems include components that form the complex system. These components can have logical, temporal, and other kinds of dependencies between the components that form the system. For example, for a given component to complete a task from start to end, it may need to call upon other components, or chains of components, in order to perform required processing, or the given component may require information or data from one or more other components or a chain of components for completion of the task. Large, complex chains of such dependencies can develop, especially as a system increases in size and complexity. A particular kind of dependency, called a circular dependency, or cycle, when combined with other distinct circular dependencies, can lead to large, tangled webs of dependencies that can be particularly difficult to identify and understand. A large complex system that includes dependencies between components can be, for example, a transportation system, a business workflow process, an inventory control system, a manufacturing system, a large complex software system or a variety of other systems.
Most large software systems are susceptible to a form of software design defect due to architectural complexity. As these software systems evolve over time, changes to existing software components (such as those necessary to fix problems or to meet new requirements) are required. In a complex network of interdependent and cyclically dependent modules, changes to one component can often exhibit a ripple effect across a software architecture and impact other seemingly non-related components. Tracking down and understanding these ripple effects can be very difficult to do without the assistance of software tools. Since many developers are typically involved in the development of large, complex software systems, very few if any developers may have knowledge of the particulars of the entire application's source code and all the relationships between components that may exist at any particular stage of development of the system. As the size and complexity of a software system increases, the result can be that it becomes increasingly difficult and costly to perform maintenance and enhancement, which can lead to a large increase in the number, severity, scope and cost to repair defects.
A major root cause of the increased difficulty in software maintenance, enhancement and defect corrections lies in the development over time of complex webs of dependency relationships among the software components or modules that make up the system. These complex webs evolve for many reasons, including complexity of the problem, developer turnover, and lack of design expertise. Cyclic dependencies in particular can substantially increase the difficulty when software changes are required since a change in a given module that is part of one or more cyclic dependencies may require changes in many other modules in any of the cycles that include the given component. Changes to any module that is not part of a cyclic dependency, but that depends upon any module contained in a cyclic dependency, will in general require examination of all modules in the relevant cyclic dependencies. For example, the simplest form of a cyclic dependency occurs when a first module needs information from a second module in order to compile and run, and vice versa. When the cyclic dependency relationships involve, for example, 100 or 150 modules, the effect is often a substantial multiplier on the efforts required to fix any module within the cyclic dependency chain or any module that depends upon a module in the cyclic dependency chain. Therefore, it can be especially desirable to reduce or eliminate large webs of cyclic dependencies in software systems, but at the same time these large webs are the most difficult to identify and understand in order to correct these large cyclic dependencies. There are several commonly understood ways to redesign software systems to avoid or reduce cyclic and other types of unnecessarily complicated patterns of dependencies.